/*
 * @(#)Engine.java 	1.0 2010/07/29
 *
 * Copyright 2010 guyven and David Croft. All rights reserved.
 */
package com.iawg.attrition.engine;

import com.iawg.attrition.engine.messaging.Message;
import com.iawg.attrition.engine.messaging.MessageHandler;
import com.iawg.attrition.engine.renderer.Renderer;

/**
 * The back end processing class.
 * 
 * @author guyven
 * @version 1.0 2010/07/29
 */
public abstract class Engine<R extends Renderer<?>, H extends MessageHandler<?,M>, M extends Message<?,M>> implements Runnable{
	private R renderer = null;
	/** The message handler the engine uses to process message data. */
	private H messageHandler = null;
	/** If the engine is currently is running. */
	private boolean isRunning = true;
//	/** The map the engine has currently loaded */
//	Map map = null;
//	/** The list that will hold all of the Actors the map contains. **/
//	ArrayList<Actor> actorArrayList = new ArrayList<Actor>();

	/** Internal constructor constructs a new engine will all values set to null. */
	protected Engine(){}	

	/**
	 * Constructs a new Engine with the given attritionRenderer and message handler.
	 * 
	 * @param renderer The attritionRenderer the engine will output to. 
	 * @param messageHandler The message handler the engine uses to process message data. 
	 */
	protected Engine (R renderer, H messageHandler){
		this.renderer = renderer;
		this.messageHandler = messageHandler;
		new Thread(this).start();
		new Thread(this.renderer).start();
	}

	/** @return The message handler the engine uses to process message data. */
	public H getMessageHandler() {
		return messageHandler;
	}

	/** @return The attritionRenderer the engine will output to.*/
	public R getRenderer(){
		return renderer;
	}

	@Override
	public void run() {
		try {
			while(isRunning){
				renderer.print("Engine Tick.");
				processMessage(messageHandler.getNextMessage());
			}
		} catch (InterruptedException interruptedException) {
			renderer.print("Engine was interupted.");
			interruptedException.printStackTrace();
		}finally{
			renderer.close();
		}
	}

	/**
	 * Processes the given message and performs the appropriate command.
	 * 
	 * @param message The message to be processed.
	 */
	protected abstract void processMessage(M message);

	/**
	 * Loads the given resource into memory.
	 * 
	 * @param resource The resource to be loaded.
	 */
	protected abstract void load(Object resource);

	/**
	 * Removes the given resource from memory.
	 * 
	 * @param resourceThe resource to be removed.
	 */
	protected abstract void release(Object resource);
}